package com.mixed.mixedserver.game.network;


import com.mixed.mixedserver.game.entity.GameMessage;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessageUnpacker;
import org.msgpack.value.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * WebSocket 游戏消息处理器
 * 处理来自前端的 WebSocket 消息，解析 MessagePack 格式的数据
 */
public class WebSocketGameHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
    
    private static final Logger logger = LoggerFactory.getLogger(WebSocketGameHandler.class);
    private final GameServerHandler gameServerHandler;
    
    public WebSocketGameHandler(GameServerHandler gameServerHandler) {
        this.gameServerHandler = gameServerHandler;
    }
    
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
        if (frame instanceof BinaryWebSocketFrame) {
            BinaryWebSocketFrame binaryFrame = (BinaryWebSocketFrame) frame;
            ByteBuf content = binaryFrame.content();
            
            try {
                // 读取长度前缀（4字节）
                if (content.readableBytes() < 4) {
                    logger.warn("Received frame with insufficient data: {} bytes", content.readableBytes());
                    return;
                }
                
                int messageLength = content.readInt();
                
                // 验证消息长度
                if (messageLength <= 0 || messageLength > 1048576) { // 1MB 限制
                    logger.warn("Invalid message length: {}", messageLength);
                    ctx.close();
                    return;
                }
                
                // 检查是否有足够的数据
                if (content.readableBytes() < messageLength) {
                    logger.warn("Insufficient data for message. Expected: {}, Available: {}", 
                               messageLength, content.readableBytes());
                    return;
                }
                
                // 读取消息数据
                byte[] messageData = new byte[messageLength];
                content.readBytes(messageData);
                
                // 解析 MessagePack 数据
                GameMessage gameMessage = parseMessagePackData(messageData);
                if (gameMessage != null) {
                    // 委托给原有的游戏处理器
                    gameServerHandler.channelRead(ctx, gameMessage);
                }
                
            } catch (Exception e) {
                logger.error("Error processing WebSocket message", e);
                ctx.close();
            }
        } else {
            logger.warn("Unsupported WebSocket frame type: {}", frame.getClass().getSimpleName());
        }
    }
    
    /**
     * 解析 MessagePack 数据为 GameMessage
     */
    private GameMessage parseMessagePackData(byte[] data) {
        try {
            MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(data);
            Value value = unpacker.unpackValue();
            
            if (value.isMapValue()) {
                Map<Value, Value> map = value.asMapValue().map();
                
                String messageType = null;
                String playerId = null;
                Object messageData = null;
                
                // 遍历 map 提取字段
                for (Map.Entry<Value, Value> entry : map.entrySet()) {
                    if (entry.getKey().isStringValue()) {
                        String key = entry.getKey().asStringValue().asString();
                        Value val = entry.getValue();
                        
                        switch (key) {
                            case "type":
                                if (val.isStringValue()) {
                                    messageType = val.asStringValue().asString();
                                }
                                break;
                            case "playerId":
                                if (val.isStringValue()) {
                                    playerId = val.asStringValue().asString();
                                }
                                break;
                            case "data":
                                if (!val.isNilValue()) {
                                    messageData = parseMessageData(val);
                                }
                                break;
                        }
                    }
                }
                
                if (messageType != null) {
                    GameMessage gameMessage = new GameMessage();
                    try {
                        gameMessage.setType(GameMessage.MessageType.valueOf(messageType));
                        gameMessage.setPlayerId(playerId);
                        gameMessage.setData(messageData);
                        return gameMessage;
                    } catch (IllegalArgumentException e) {
                        logger.warn("Unknown message type: {}", messageType);
                    }
                }
            }
            
            unpacker.close();
        } catch (Exception e) {
            logger.error("Error parsing MessagePack data", e);
        }
        
        return null;
    }
    
    /**
     * 解析消息数据部分
     */
    private Object parseMessageData(Value value) {
        if (value.isMapValue()) {
            // 返回简单的 Map 结构，让 GameServerHandler 处理具体的数据类型转换
            Map<Value, Value> map = value.asMapValue().map();
            return map;
        } else if (value.isStringValue()) {
            return value.asStringValue().asString();
        } else if (value.isIntegerValue()) {
            return value.asIntegerValue().asInt();
        } else if (value.isFloatValue()) {
            return value.asFloatValue().toFloat();
        } else if (value.isBooleanValue()) {
            return value.asBooleanValue().getBoolean();
        }
        return null;
    }
    
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("WebSocket connection established: {}", ctx.channel().remoteAddress());
        
        // 添加 WebSocket 消息编码器到管道中
        ctx.pipeline().addBefore("webSocketHandler", "webSocketMessageEncoder", new WebSocketGameMessageEncoder());
        
        gameServerHandler.channelActive(ctx);
    }
    
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        logger.info("WebSocket connection closed: {}", ctx.channel().remoteAddress());
        gameServerHandler.channelInactive(ctx);
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("WebSocket handler exception", cause);
        gameServerHandler.exceptionCaught(ctx, cause);
    }
}